using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using FireStarter.Base;
using Firestarter.DB.Schema.Test.Logic;
using Firestarter.Test.Base;
using FireStarterModeller.BO;
using Habanero.Base;
using Habanero.Base.Exceptions;
using Habanero.BO;
using Habanero.Test.Structure;
using NUnit.Framework;

namespace FireStarterModeller.Test.BO
{
    /// <summary>
    /// Provides a place to write custom tests for DMPropertyType objects.
    /// This file is only written once and can be changed.  The Def file
    /// attached to this as a dependent is rewritten with each regeneration
    /// and contains the standard tests for DMPropertyType.
    /// Regenerate this test project whenever there have been changes to the
    /// business objects.
    /// If tests are failing due to a unique setup in your application,
    /// you can either override the Create methods in TestUtils, or you
    /// can add the test to the ignore list below and reimplement it here.
    /// </summary>
    public partial class TestDMPropertyType
    {
        [SetUp]
        public override void SetupTest()
        {
            //Runs every time that any testmethod is executed
            base.SetupTest();
        }

        [TestFixtureSetUp]
        public void TestFixtureSetup()
        {
            //------------------------------------------------------------
            // Use this list to ignore generated tests that are failing
            // due to a unique condition in your application.
            // Remember to reimplement the test here.
            //------------------------------------------------------------
            //_ignoreList.Add("TestMethodName", "Reason for ignoring it");
            base.SetupFixture();
        }

        [TearDown]
        public override void TearDownTest()
        {
            //runs every time any testmethod is complete
            base.TearDownTest();
        }

        [Test]
        public void Test_ToString()
        {
            //---------------Set up test pack-------------------
            DMPropertyType dmPropertyType = TestUtilsDMPropertyType.CreateUnsavedValidDMPropertyType();
            //---------------Assert Precondition----------------
            Assert.IsFalse(String.IsNullOrEmpty(dmPropertyType.PropertyTypeName), "PropertyTypeName Should not be null");
            //---------------Execute Test ----------------------
            string actualToString = dmPropertyType.ToString();
            //---------------Test Result -----------------------
            Assert.AreEqual(dmPropertyType.PropertyTypeName, actualToString);
        }

        [Test]
        public void Test_Construct_WithAssemblyNameAndTypeName()
        {
            //---------------Set up test pack-------------------
            string assemblyName = TestUtilsShared.GetRandomString();
            string typeName = TestUtilsShared.GetRandomString();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            DMPropertyType dmPropertyType = new DMPropertyType(assemblyName, typeName);
            //---------------Test Result -----------------------
            Assert.AreEqual(assemblyName, dmPropertyType.AssemblyName);
            Assert.AreEqual(typeName, dmPropertyType.PropertyTypeName);
        }

        [Test]
        public void Test_ToString_TableNameNull()
        {
            //---------------Set up test pack-------------------
            DMPropertyType dmPropertyType = TestUtilsDMPropertyType.CreateUnsavedValidDMPropertyType();
            dmPropertyType.PropertyTypeName = null;
            //---------------Assert Precondition----------------
            Assert.IsTrue(String.IsNullOrEmpty(dmPropertyType.PropertyTypeName), "PropertyTypeName Should be null");
            //---------------Execute Test ----------------------
            string actualToString = dmPropertyType.ToString();
            //---------------Test Result -----------------------
            Assert.AreEqual(dmPropertyType.PropertyTypeID.ToString(), actualToString);
        }
        [Test]
        public void Test_ToString_TableNameNull_PropertyTypeIDNull()
        {
            //---------------Set up test pack-------------------
            DMPropertyType dmPropertyType = TestUtilsDMPropertyType.CreateUnsavedValidDMPropertyType();
            dmPropertyType.PropertyTypeName = null;
            dmPropertyType.PropertyTypeID = null;
            //---------------Assert Precondition----------------
            Assert.IsTrue(String.IsNullOrEmpty(dmPropertyType.PropertyTypeName), "PropertyTypeName Should be null");
            Assert.IsNull(dmPropertyType.PropertyTypeID);
            //---------------Execute Test ----------------------
            string actualToString = dmPropertyType.ToString();
            //---------------Test Result -----------------------
            Assert.AreEqual("-unnamed propertyType-", actualToString);
        }
        [Test]
        public void Test_InsertNewPropertyTypeInfo()
        {
            //---------------Set up test pack-------------------
            DMPropertyType dmPropertyType = TestUtilsShared.CreateUnsavedValidPropertyTypeInfo();

            //---------------Assert Precondition----------------
            Assert.IsTrue(dmPropertyType.Status.IsNew);

            //---------------Execute Test ----------------------
            dmPropertyType.Save();

            //---------------Test Result -----------------------
            Assert.IsFalse(dmPropertyType.Status.IsNew);
        }

        [Test]
        public void Test_InsertNewPropertyTypeInfo_Invalid()
        {
            //---------------Set up test pack-------------------
            DMPropertyType dmPropertyType = new DMPropertyType();

            //---------------Assert Precondition----------------
            Assert.IsTrue(dmPropertyType.Status.IsNew);

            //---------------Execute Test ----------------------
            try
            {
                dmPropertyType.Save();
                Assert.Fail("expected Err");
            }
            //---------------Test Result -----------------------
            catch (BusObjectInAnInvalidStateException ex)
            {
                StringAssert.Contains("Type Name' is a compulsory field and has no value", ex.Message);

            }
            Assert.IsTrue(dmPropertyType.Status.IsNew);
        }

        [Test]
        public void Test_DeletePropertyTypeInfo()
        {
            //---------------Set up test pack-------------------
            DMPropertyType dmPropertyType = TestUtilsShared.CreateSavedPropertyTypeInfo();

            //---------------Assert Precondition----------------
            Assert.IsFalse(dmPropertyType.Status.IsNew);
            string message;
            Assert.IsTrue(dmPropertyType.IsDeletable(out message));

            //---------------Execute Test ----------------------
            dmPropertyType.MarkForDelete();
            dmPropertyType.Save();

            //---------------Test Result -----------------------  
            Assert.IsTrue(dmPropertyType.Status.IsNew);
            Assert.IsTrue(dmPropertyType.Status.IsDeleted);
        }

        //[Test]
        //public void Test_UpdatePropertyTypeInfo()
        //{
        //    //---------------Set up test pack-------------------
        //    DMPropertyType dmPropertyType = TestUtils.CreateSavedPropertyTypeInfo();

        //    //---------------Assert Precondition----------------
        //    Assert.IsFalse(dmPropertyType.Status.IsNew);
        //    string message;
        //    Assert.IsTrue(dmPropertyType.IsEditable(out message));

        //    //---------------Execute Test ----------------------
        //    dmPropertyType.AssemblyName = TestUtilsShared.GetRandomString();
        //    dmPropertyType.PropertyTypeName = TestUtilsShared.GetRandomString();
        //    dmPropertyType.Save();

        //    //---------------Test Result -----------------------
        //    Assert.IsFalse(dmPropertyType.Status.IsNew);
        //}
//
//        [Test]
//        public void Test_SetPropertyTypeName_SetsThePropertyTypeID()
//        {
//            //---------------Set up test pack-------------------
//            const string propertyTypeName = "String";
//            DMPropertyType propertyType = new DMPropertyType();
//            //---------------Assert Precondition----------------
//            Assert.IsNull(propertyType.PropertyTypeName);
//            Assert.IsNull(propertyType.AssemblyName);
//            Assert.IsNotNull(propertyType.PropertyTypeID);
//            //---------------Execute Test ----------------------
//            propertyType.PropertyTypeName = propertyTypeName;
//            //---------------Test Result -----------------------
//            Assert.IsNull(propertyType.AssemblyName);
//            Assert.AreEqual(propertyTypeName, propertyType.PropertyTypeName);
//            Assert.AreEqual(propertyType.AssemblyName + "." + propertyType.PropertyTypeName , propertyType.PropertyTypeID);
//        }
        [Test]
        public void Test_SetPropertyTypeName_AlternateConstructor_SetsThePropertyTypeID()
        {
            //---------------Set up test pack-------------------
            const string propertyTypeName = "String";
            DMPropertyType propertyType = new DMPropertyType();
            IFormatter formatter = new BinaryFormatter();
            MemoryStream memoryStream = new MemoryStream();
            formatter.Serialize(memoryStream, propertyType);
            memoryStream.Seek(0, SeekOrigin.Begin);
            BusinessObjectManager.Instance.ClearLoadedObjects();
            propertyType = (DMPropertyType)formatter.Deserialize(memoryStream);
            string originalName = propertyType.PropertyTypeName;
            //---------------Assert Precondition----------------
            Assert.IsNull(propertyType.PropertyTypeName);
            Assert.IsNull(propertyType.AssemblyName);
            //---------------Execute Test ----------------------
            propertyType.PropertyTypeName = propertyTypeName;
            //---------------Test Result -----------------------
            Assert.AreNotEqual(propertyType.PropertyTypeName, originalName);

        }
//        [Test]
//        public void Test_SetAssemblyName_SetsThePropertyTypeID()
//        {
//            //---------------Set up test pack-------------------
//            const string assemblyName = "System";
//            DMPropertyType propertyType = new DMPropertyType();
//            //---------------Assert Precondition----------------
//            Assert.IsNull(propertyType.PropertyTypeName);
//            Assert.IsNull(propertyType.AssemblyName);
//            Assert.IsNotNull(propertyType.PropertyTypeID);
//            //---------------Execute Test ----------------------
//            propertyType.AssemblyName = assemblyName;
//            //---------------Test Result -----------------------
//            Assert.IsNull(propertyType.PropertyTypeName);
//            Assert.AreEqual(assemblyName, propertyType.AssemblyName);
//            Assert.AreEqual(propertyType.AssemblyName + "." + propertyType.PropertyTypeName , propertyType.PropertyTypeID);
//        }

        [Test]
        public void Test_GetPropertyTypeFullName_ShouldReturnAssemblyPlusTypeName()
        {
            //---------------Set up test pack-------------------
            const string assemblyName = "System";
            const string typeName = "String";
            DMPropertyType propertyType = new DMPropertyType();
            propertyType.AssemblyName = assemblyName;
            propertyType.PropertyTypeName = typeName;
            //---------------Assert Precondition----------------
            Assert.AreEqual(typeName, propertyType.PropertyTypeName);
            Assert.AreEqual(assemblyName, propertyType.AssemblyName);
            //---------------Execute Test ----------------------
            string propertyTypeFullName = propertyType.PropertyTypeFullName;
            //---------------Test Result -----------------------
            Assert.AreEqual(assemblyName +"." + typeName, propertyTypeFullName);
        }

        [Test]
        public void Test_GetActualTypeReturnsCorrectType()
        {
            //---------------Set up test pack-------------------
            const string assemblyName = "System";
            const string typeName = "String";
            DMPropertyType propertyType = new DMPropertyType();
            propertyType.AssemblyName = assemblyName;
            propertyType.PropertyTypeName = typeName;
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            Type actualPropertyType = propertyType.GetActualType();
            //---------------Test Result -----------------------
            Assert.AreEqual("System.String",actualPropertyType.FullName);
        }

        [Test]
        public void Test_IsDeletable_WhenNull_ShouldReturnTrue()
        {
            //---------------Set up test pack-------------------
            const string assemblyName = null;
            DMPropertyType propertyType = CreatePropertyType();
            SetAssemblyName(propertyType, assemblyName);
            //---------------Assert Precondition----------------
            Assert.IsTrue(string.IsNullOrEmpty(assemblyName), "Assembly Name should be null");
//            Assert.IsNull(propertyType.AssemblyName);
            //---------------Execute Test ----------------------
            string message;
            bool isDeletable = propertyType.IsDeletable(out message);
            //---------------Test Result -----------------------
            Assert.IsTrue(isDeletable);
        }

        [Test]
        public void Test_IsDeletable_WhenAssemblyNameStartsWithSystem_ShouldReturnFalse()
        {
            //---------------Set up test pack-------------------
            const string assemblyName = "System";
            const string typeName = "String";
            DMPropertyType propertyType = CreatePropertyType();
            SetAssemblyName(propertyType, assemblyName);
            SetPropertyTypeName(propertyType, typeName);
            //---------------Assert Precondition----------------
            Assert.IsFalse(string.IsNullOrEmpty(assemblyName), "Assembly Name should not be null");
            Assert.AreEqual("System",assemblyName);
            //---------------Execute Test ----------------------
            string message;
            bool isDeletable = propertyType.IsDeletable(out message);
            //---------------Test Result -----------------------
            Assert.IsFalse(isDeletable);
            StringAssert.Contains("The Property Type '" + propertyType.PropertyTypeName + "' with the Assembly Name '"
                                   + propertyType.AssemblyName + "' cannot be deleted.",message);
        }

        [Test]
        public void Test_IsDeletable_WhenAssemblyNameDoesNotStartWithSystem_ShouldReturnTrue()
        {
            //---------------Set up test pack-------------------
            const string assemblyName = "Other";
            DMPropertyType propertyType = CreatePropertyType();
            SetAssemblyName(propertyType, assemblyName);
            //---------------Assert Precondition----------------
            Assert.IsFalse(string.IsNullOrEmpty(assemblyName), "Assembly Name should not be null");
            Assert.AreNotEqual("System",assemblyName);
            //---------------Execute Test ----------------------
            string message;
            bool isDeletable = propertyType.IsDeletable(out message);
            //---------------Test Result -----------------------
            Assert.IsTrue(isDeletable);
        }


        [Test]
        public void Test_IsEditable_WhenNull_ShouldReturnTrue()
        {
            //---------------Set up test pack-------------------
            const string assemblyName = null;
            DMPropertyType propertyType = CreatePropertyType();
            SetAssemblyName(propertyType, assemblyName);
            //---------------Assert Precondition----------------
            Assert.IsTrue(string.IsNullOrEmpty(assemblyName), "Assembly Name should be null");
            //            Assert.IsNull(propertyType.AssemblyName);
            //---------------Execute Test ----------------------
            string message;
            bool isEditable = propertyType.IsEditable(out message);
            //---------------Test Result -----------------------
            Assert.IsTrue(isEditable);
        }

        [Test]
        public void Test_IsEditable_WhenAssemblyNameStartsWithSystem_ShouldReturnFalse()
        {
            //---------------Set up test pack-------------------
            const string assemblyName = "System";
            const string typeName = "String";
            DMPropertyType propertyType = CreatePropertyType();
            SetAssemblyName(propertyType, assemblyName);
            SetPropertyTypeName(propertyType, typeName);
            //---------------Assert Precondition----------------
            Assert.IsFalse(string.IsNullOrEmpty(assemblyName), "Assembly Name should not be null");
            Assert.AreEqual("System", assemblyName);
            //---------------Execute Test ----------------------
            string message;
            bool isEditable = propertyType.IsEditable(out message);
            //---------------Test Result -----------------------
            Assert.IsFalse(isEditable);
            StringAssert.Contains("The Property Type '" + propertyType.PropertyTypeName + "' with the Assembly Name '"
                                   + propertyType.AssemblyName + "' cannot be edited.", message);
        }

        [Test]
        public void Test_IsEditable_WhenAssemblyNameDoesNotStartWithSystem_ShouldReturnTrue()
        {
            //---------------Set up test pack-------------------
            const string assemblyName = "Other";
            DMPropertyType propertyType = CreatePropertyType();
            SetAssemblyName(propertyType, assemblyName);
            //---------------Assert Precondition----------------
            Assert.IsFalse(string.IsNullOrEmpty(assemblyName), "Assembly Name should not be null");
            Assert.AreNotEqual("System", assemblyName);
            //---------------Execute Test ----------------------
            string message;
            bool isEditable = propertyType.IsEditable(out message);
            //---------------Test Result -----------------------
            Assert.IsTrue(isEditable);
        }


        private DMPropertyType CreatePropertyType()
        {
            return new DMPropertyType();
        }


        private void SetAssemblyName(DMPropertyType propertyType, string assemblyName)
        {
            propertyType.AssemblyName = assemblyName;
        }


        private void SetPropertyTypeName(DMPropertyType propertyType, string typeName)
        {
            propertyType.PropertyTypeName = typeName;
        }
     [Test]
        public void Test_GetParent()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = new DMSolution();
            DMPropertyType dmPropertyType = new DMPropertyType();
            dmSolution.PropertyTypes.Add(dmPropertyType);
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            IModelElement parent = ((IModelPropertyType) dmPropertyType).Parent;
            //---------------Test Result -----------------------
            Assert.AreSame(dmSolution, parent);
        }

        [Test]
        public void Test_SetParentExceptionThrown()
        {
            //---------------Set up test pack-------------------
            DMPropertyType dmPropertyType = new DMPropertyType();

            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            Exception exceptionThrown = null;
            try
            {
                ((IModelPropertyType) dmPropertyType).Parent = new DMSolution();
            }
            catch (Exception ex)
            {
                exceptionThrown = ex;
            }
            //---------------Test Result -----------------------
            Assert.IsNotNull(exceptionThrown);
            Assert.IsInstanceOf(typeof (HabaneroDeveloperException), exceptionThrown);
            StringAssert.Contains
                ("Set the parent of the PropertyType by setting the related Solution object", exceptionThrown.Message);
        }

        [Test]
        public void Test_IsValueType_String_False()
        {
            //---------------Set up test pack-------------------
            DMPropertyType dmPropertyType = new DMPropertyType();
            dmPropertyType.AssemblyName = "System";
            dmPropertyType.PropertyTypeName = "String";
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            bool actualResult = ((IModelPropertyType) dmPropertyType).IsValueType;
            //---------------Test Result -----------------------
            Assert.IsFalse(actualResult);
        }

        [Test]
        public void Test_IsValueType_Guid_True()
        {
            //---------------Set up test pack-------------------
            DMPropertyType dmPropertyType = new DMPropertyType();
            dmPropertyType.AssemblyName = "System";
            dmPropertyType.PropertyTypeName = "Guid";
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            bool actualResult = ((IModelPropertyType) dmPropertyType).IsValueType;
            //---------------Test Result -----------------------
            Assert.IsTrue(actualResult);
        }

        [Test]
        public void Test_IsValueType_Random_False()
        {
            //---------------Set up test pack-------------------
            DMPropertyType dmPropertyType = new DMPropertyType();
            dmPropertyType.AssemblyName = GetRandomString();
            dmPropertyType.PropertyTypeName = GetRandomString();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            bool actualResult = ((IModelPropertyType) dmPropertyType).IsValueType;
            //---------------Test Result -----------------------
            Assert.IsFalse(actualResult);
        }

        [Test]
        public void Test_FindOrCreate_WhenNullSolution_ShouldThrowError()
        {
            //---------------Set up test pack-------------------
            
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            try
            {
                DMPropertyType.FindOrCreate(null, "fdaf", "fdafd");
                Assert.Fail("expected ArgumentNullException");
            }
                //---------------Test Result -----------------------
            catch (ArgumentNullException ex)
            {
                StringAssert.Contains("Value cannot be null", ex.Message);
                StringAssert.Contains("solution", ex.ParamName);
            }
        }

        [Test]
        public void Test_IsDeletable_WhenIsSystem_WhenForeceDeleteFalse_ShouldBeFalse()
        {
            //---------------Set up test pack-------------------
            DMPropertyType dmPropertyType = new DMPropertyType();
            dmPropertyType.AssemblyName = "System";
            dmPropertyType.PropertyTypeName = GetRandomString();
            //---------------Assert Precondition----------------
            Assert.IsTrue(dmPropertyType.AssemblyName.StartsWith("System"));
            Assert.IsFalse(dmPropertyType.ForceDelete);
            //---------------Execute Test ----------------------
            string message;
            var isDeletable = dmPropertyType.IsDeletable(out message);
            //---------------Test Result -----------------------
            Assert.IsFalse(isDeletable);
        }

        private static string GetRandomString()
        {
            return RandomValueGen.GetRandomString();
        }

        [Test]
        public void Test_IsDeletable_WhenIsSystem_WhenForeceDeleteTrue_ShouldBeTrue()
        {
            //---------------Set up test pack-------------------
            DMPropertyType dmPropertyType = new DMPropertyType();
            dmPropertyType.AssemblyName = "System";
            dmPropertyType.PropertyTypeName = GetRandomString();
            dmPropertyType.ForceDelete = true;
            //---------------Assert Precondition----------------
            Assert.IsTrue(dmPropertyType.AssemblyName.StartsWith("System"));
            Assert.IsTrue(dmPropertyType.ForceDelete);
            //---------------Execute Test ----------------------
            string message;
            var isDeletable = dmPropertyType.IsDeletable(out message);
            //---------------Test Result -----------------------
            Assert.IsTrue(isDeletable);
        }
    }
  }
